package com.xiaoyu.lanling.media.image;

import android.graphics.Bitmap;
import android.net.Uri;
import android.text.TextUtils;

import androidx.annotation.ColorInt;
import androidx.annotation.Nullable;

import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.controller.ControllerListener;
import com.facebook.drawee.generic.RoundingParams;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.drawee.view.DraweeView;
import com.facebook.imagepipeline.common.ImageDecodeOptions;
import com.facebook.imagepipeline.common.ResizeOptions;
import com.facebook.imagepipeline.image.ImageInfo;
import com.facebook.imagepipeline.listener.RequestListener;
import com.facebook.imagepipeline.request.ImageRequest;
import com.facebook.imagepipeline.request.ImageRequestBuilder;
import com.facebook.imagepipeline.request.Postprocessor;
import com.facebook.imageutils.BitmapUtil;
import com.xiaoyu.base.image.ImageUrlManager;
import com.xiaoyu.lanling.R;

import java.io.File;

import in.srain.cube.util.LocalDisplay;
import in.srain.cube.util.UriUtil;
import in.srain.cube.util.StringUtil;

import static in.srain.cube.util.LocalDisplay.SCREEN_HEIGHT_PIXELS;
import static in.srain.cube.util.LocalDisplay.SCREEN_WIDTH_PIXELS;

public class ImageLoadParam {

    private static int sDefaultFailResId;

    private final Uri mUri;
    private final ImageRequest mImageRequest;
    private final int mPlaceHolderResId;
    private final int mFailImageResId;
    private final int mOverlayResId;
    @Nullable
    private final RoundingParams mRoundingParams;
    private final boolean mIsAutoPlay;
    private final ControllerListener<ImageInfo> mImageInfoControllerListener;
    private final ImageLoadParam mLowResImageLoadParam;

    static {
        sDefaultFailResId = R.drawable.icon_normal_empty;
    }

    protected ImageLoadParam(ImageLoadParamBuilder<?> builder) {
        mUri = builder.mUri;
        mImageRequest = builder.mImageRequest;
        mPlaceHolderResId = builder.mPlaceHolderResId;
        mFailImageResId = builder.mFailImageResId;
        mOverlayResId = builder.mOverlayResId;
        mRoundingParams = builder.mRoundingParams;
        mIsAutoPlay = builder.mIsAutoPlay;
        mImageInfoControllerListener = builder.mControllerListener;
        mLowResImageLoadParam = builder.mLowResImageLoadParam;
    }

    public static ImageLoadParamBuilder newBuilder() {
        return new ImageLoadParamBuilder();
    }

    @Nullable
    public RoundingParams getRoundingParams() {
        return mRoundingParams;
    }

    public int getPlaceHolderResId() {
        return mPlaceHolderResId;
    }

    public int getFailImageResId() {
        return mFailImageResId;
    }

    public int getOverlayResId() {
        return mOverlayResId;
    }

    public Uri getUri() {
        return mUri;
    }

    public String getKey() {
        return mUri.toString();
    }

    public void setControllerFor(DraweeView simpleDraweeView) {
        DraweeController controller = Fresco.newDraweeControllerBuilder()
                .setOldController(simpleDraweeView.getController())
                .setControllerListener(mImageInfoControllerListener)
                .setAutoPlayAnimations(mIsAutoPlay)
                .setLowResImageRequest(mLowResImageLoadParam == null ? null : mLowResImageLoadParam.mImageRequest)
                .setImageRequest(mImageRequest)
                .build();
        simpleDraweeView.setController(controller);
    }

    public static class ImageLoadParamBuilder<T extends ImageLoadParamBuilder<T>> {

        private Uri mUri;
        private String mOriginUrl;
        private int mWidth;
        private int mHeight;
        private int mMaxBitmapSize;
        private int mPlaceHolderResId;
        private int mFailImageResId;
        public int mOverlayResId;
        private boolean mRounded;
        private float mRadius;
        private int mRoundingBorderWidth;
        private int mRoundingBorderColor;
        private boolean mIsAutoPlay = true;
        private boolean mIsSmallCacheChoice = false;
        private boolean mEnableEmptyUrl = false;
        private boolean mProgressiveRenderingEnabled = false;
        private boolean mLocalThumbnailPreviewsEnabled = false;
        private boolean mKeepOriginal = false;
        private Postprocessor mPostprocessor;
        private RequestListener mRequestListener;
        private Bitmap.Config mBitmapConfig;
        private ControllerListener<ImageInfo> mControllerListener;
        private RoundingParams mRoundingParams;
        private ImageRequest mImageRequest;
        private ImageLoadParam mLowResImageLoadParam;
        private ImageRequest mLowResImageRequest;

        public T setUrl(String url) {
            if (TextUtils.isEmpty(url)) {
                mOriginUrl = mEnableEmptyUrl ? StringUtil.blank() : UriUtil.getUriForResourceId(sDefaultFailResId).toString();
                return self();
            }
            if (ImageUrlManager.getInstance().isLocalUrl(url)) {
                return setLocalFile(url);
            }

            mOriginUrl = url;
            return self();
        }

        public T setEnableEmptyUrl(boolean enableEmptyUrl) {
            mEnableEmptyUrl = enableEmptyUrl;
            return self();
        }

        public T setResId(int resId) {
            mOriginUrl = UriUtil.getUriForResourceId(resId).toString();
            return self();
        }

        public T setLocalFile(String path) {
            mOriginUrl = ImageUrlManager.getInstance().processLocalUrl(path);
            return self();
        }

        public T setFile(String path) {
            mOriginUrl = UriUtil.getUriForFile(new File(path)).toString();
            return self();
        }

        public T setAssetFile(String assetFile) {
            mOriginUrl = UriUtil.getUriForAssetFile(assetFile).toString();
            return self();
        }

        public T setPlaceHolderResId(int placeHolderResId) {
            mPlaceHolderResId = placeHolderResId;
            return self();
        }

        public T setFailImageResId(int failImageResId) {
            mFailImageResId = failImageResId;
            return self();
        }

        public T setOverlayResId(int overlayResId) {
            mOverlayResId = overlayResId;
            return self();
        }

        public T setMaxBitmapSize(int maxBitmapSize) {
            this.mMaxBitmapSize = maxBitmapSize;
            return self();
        }

        public T setWidthToFullScreen() {
            mWidth = SCREEN_WIDTH_PIXELS;
            return self();
        }

        public T setWidthInDP(int dp) {
            mWidth = LocalDisplay.dp2px(dp);
            return self();
        }

        public T setWidth(int width) {
            this.mWidth = width;
            return self();
        }

        public T setHeightToFullScreen() {
            mHeight = SCREEN_HEIGHT_PIXELS;
            return self();
        }

        public T setHeightInDP(int dp) {
            mHeight = LocalDisplay.dp2px(dp);
            return self();
        }

        public T setHeight(int height) {
            mHeight = height;
            return self();
        }

        public T setSizeInDP(int dp) {
            return setWidthInDP(dp).setHeightInDP(dp);
        }

        public T setSize(float size) {
            return setWidth((int) size).setHeight((int) size);
        }

        public T setSize(int size) {
            return setWidth(size).setHeight(size);
        }

        public T setRounded(boolean rounded) {
            mRounded = rounded;
            return self();
        }

        public T setCornersRadiusInDP(float radius) {
            return setCornersRadius(LocalDisplay.dp2px(radius));
        }

        public T setCornersRadius(float radius) {
            mRadius = radius;
            return self();
        }

        public T setRoundingBorderWidth(int width) {
            mRoundingBorderWidth = width;
            return self();
        }

        public T setRoundingBorderColor(@ColorInt int color) {
            mRoundingBorderColor = color;
            return self();
        }

        public T setAutoPlay(boolean autoPlay) {
            mIsAutoPlay = autoPlay;
            return self();
        }

        public T setSmallCacheChoice(boolean isSmallCacheChoice) {
            mIsSmallCacheChoice = isSmallCacheChoice;
            return self();
        }

        public T setPostProcessor(Postprocessor postProcessor) {
            mPostprocessor = postProcessor;
            return self();
        }

        public T setRequestListener(RequestListener requestListener) {
            mRequestListener = requestListener;
            return self();
        }

        public T setBitmapConfig(Bitmap.Config bitmapConfig) {
            mBitmapConfig = bitmapConfig;
            return self();
        }

        public T setProgressiveRenderingEnabled(boolean enable) {
            mProgressiveRenderingEnabled = enable;
            return self();
        }

        public T setLocalThumbnailPreviewsEnabled(boolean enable) {
            mLocalThumbnailPreviewsEnabled = enable;
            return self();
        }

        public T setControllerListener(ControllerListener<ImageInfo> controllerListener) {
            this.mControllerListener = controllerListener;
            return self();
        }

        public T setKeepOriginal(boolean keepOriginal) {
            this.mKeepOriginal = keepOriginal;
            return self();
        }

        public T setLowResImageLoadParam(ImageLoadParam lowResImageLoadParam) {
            this.mLowResImageLoadParam = lowResImageLoadParam;
            return self();
        }

        @SuppressWarnings("unchecked")
        protected final T self() {
            return (T) this;
        }

        protected void processParam() {
            try {
                mUri = Uri.parse(ImageUrlManager.getInstance().getRemoteUrl(mOriginUrl, mWidth, mKeepOriginal));
            } catch (Exception e) {
                mUri = UriUtil.getUriForResourceId(sDefaultFailResId);
                e.printStackTrace();
            }

            if (mRadius > 0) {
                mRoundingParams = RoundingParams.fromCornersRadius(mRadius);
            }
            if (mRounded) {
                mRoundingParams = RoundingParams.fromCornersRadius(mWidth / 2f);
                mRoundingParams.setRoundAsCircle(true);
            }

            if (mRoundingBorderWidth > 0 && mRoundingBorderColor != -1) {
                mRoundingParams.setBorder(mRoundingBorderColor, mRoundingBorderWidth);
            }

            ImageRequestBuilder mImageRequestBuilder = ImageRequestBuilder.newBuilderWithSource(mUri);
            if (mHeight > 0 && mWidth > 0) {
                mImageRequestBuilder.setResizeOptions(new ResizeOptions(mWidth, mHeight, Math.max(mMaxBitmapSize, BitmapUtil.MAX_BITMAP_SIZE)));
            }
            if (mBitmapConfig != null) {
                ImageDecodeOptions decodeOptions = ImageDecodeOptions.newBuilder().setBitmapConfig(mBitmapConfig).build();
                mImageRequestBuilder.setImageDecodeOptions(decodeOptions);
            }
            mImageRequestBuilder.setLocalThumbnailPreviewsEnabled(mLocalThumbnailPreviewsEnabled);
            mImageRequestBuilder.setProgressiveRenderingEnabled(mProgressiveRenderingEnabled);
            mImageRequestBuilder.setPostprocessor(mPostprocessor);
            mImageRequestBuilder.setRequestListener(mRequestListener);
            mImageRequestBuilder.setCacheChoice(mIsSmallCacheChoice ? ImageRequest.CacheChoice.SMALL : ImageRequest.CacheChoice.DEFAULT);
            mImageRequest = mImageRequestBuilder.build();
        }

        public ImageLoadParam build() {
            processParam();
            return new ImageLoadParam(this);
        }
    }
}
